<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<meta name="theme-color" content="#222"><meta name="generator" content="Hexo 6.3.0">

  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">



<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.1/css/all.min.css" integrity="sha256-Z1K5uhUaJXA7Ll0XrZ/0JhX4lAtZFpT6jkKrEDT0drU=" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.1.1/animate.min.css" integrity="sha256-PR7ttpcvz8qrF57fur/yAx1qXMFJeJFiA6pSzWi0OIE=" crossorigin="anonymous">

<script class="next-config" data-name="main" type="application/json">{"hostname":"example.com","root":"/","images":"/images","scheme":"Muse","darkmode":false,"version":"8.14.1","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12},"copycode":{"enable":false,"style":null},"bookmark":{"enable":false,"color":"#222","save":"auto"},"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"stickytabs":false,"motion":{"enable":true,"async":false,"transition":{"menu_item":"fadeInDown","post_block":"fadeIn","post_header":"fadeInDown","post_body":"fadeInDown","coll_header":"fadeInLeft","sidebar":"fadeInUp"}},"prism":false,"i18n":{"placeholder":"搜索...","empty":"没有找到任何搜索结果：${query}","hits_time":"找到 ${hits} 个搜索结果（用时 ${time} 毫秒）","hits":"找到 ${hits} 个搜索结果"},"path":"/search.xml","localsearch":{"enable":true,"trigger":"auto","top_n_per_article":-1,"unescape":false,"preload":false}}</script><script src="/js/config.js"></script>

    <meta name="description" content="Sandbox的安全机制如何设计？对于Linux而言，它的风格是一贯的。沙盒是进程而不是线程，这点非常明确。 用户权限相关Nobody 用户在许多Unix系统与类Unix系统（如Linux）中，nobody是一个没有任何权限的用户。该用户不拥有任何文件，也没有任何特殊权限。某些系统还会定义类似的用户组“nogroup”。示例： 12345678910111213141516171819202122">
<meta property="og:type" content="article">
<meta property="og:title" content="Sandbox的安全机制">
<meta property="og:url" content="http://example.com/2021/12/10/Sandbox%E7%9A%84%E5%AE%89%E5%85%A8%E6%9C%BA%E5%88%B6/index.html">
<meta property="og:site_name" content="JsyBlog">
<meta property="og:description" content="Sandbox的安全机制如何设计？对于Linux而言，它的风格是一贯的。沙盒是进程而不是线程，这点非常明确。 用户权限相关Nobody 用户在许多Unix系统与类Unix系统（如Linux）中，nobody是一个没有任何权限的用户。该用户不拥有任何文件，也没有任何特殊权限。某些系统还会定义类似的用户组“nogroup”。示例： 12345678910111213141516171819202122">
<meta property="og:locale" content="zh_CN">
<meta property="article:published_time" content="2021-12-10T13:51:54.000Z">
<meta property="article:modified_time" content="2022-09-02T14:44:06.078Z">
<meta property="article:author" content="SongyangJi">
<meta property="article:tag" content="Linux">
<meta property="article:tag" content="安全">
<meta property="article:tag" content="sandbox">
<meta name="twitter:card" content="summary">


<link rel="canonical" href="http://example.com/2021/12/10/Sandbox%E7%9A%84%E5%AE%89%E5%85%A8%E6%9C%BA%E5%88%B6/">



<script class="next-config" data-name="page" type="application/json">{"sidebar":"","isHome":false,"isPost":true,"lang":"zh-CN","comments":true,"permalink":"http://example.com/2021/12/10/Sandbox%E7%9A%84%E5%AE%89%E5%85%A8%E6%9C%BA%E5%88%B6/","path":"2021/12/10/Sandbox的安全机制/","title":"Sandbox的安全机制"}</script>

<script class="next-config" data-name="calendar" type="application/json">""</script>
<title>Sandbox的安全机制 | JsyBlog</title>
  








  <noscript>
    <link rel="stylesheet" href="/css/noscript.css">
  </noscript>
</head>

<body itemscope itemtype="http://schema.org/WebPage" class="use-motion">
  <div class="headband"></div>

  <main class="main">
    <div class="column">
      <header class="header" itemscope itemtype="http://schema.org/WPHeader"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏" role="button">
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <i class="logo-line"></i>
      <p class="site-title">JsyBlog</p>
      <i class="logo-line"></i>
    </a>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger" aria-label="搜索" role="button">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>



<nav class="site-nav">
  <ul class="main-menu menu"><li class="menu-item menu-item-home"><a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a></li><li class="menu-item menu-item-tags"><a href="/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a></li><li class="menu-item menu-item-categories"><a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a></li><li class="menu-item menu-item-archives"><a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a></li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup"><div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off" maxlength="80"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close" role="button">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div class="search-result-container no-result">
  <div class="search-result-icon">
    <i class="fa fa-spinner fa-pulse fa-5x"></i>
  </div>
</div>

    </div>
  </div>

</header>
        
  
  <aside class="sidebar">

    <div class="sidebar-inner sidebar-nav-active sidebar-toc-active">
      <ul class="sidebar-nav">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <div class="sidebar-panel-container">
        <!--noindex-->
        <div class="post-toc-wrap sidebar-panel">
            <div class="post-toc animated"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#Sandbox%E7%9A%84%E5%AE%89%E5%85%A8%E6%9C%BA%E5%88%B6%E5%A6%82%E4%BD%95%E8%AE%BE%E8%AE%A1%EF%BC%9F"><span class="nav-number">1.</span> <span class="nav-text">Sandbox的安全机制如何设计？</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%94%A8%E6%88%B7%E6%9D%83%E9%99%90%E7%9B%B8%E5%85%B3"><span class="nav-number">1.1.</span> <span class="nav-text">用户权限相关</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#Nobody-%E7%94%A8%E6%88%B7"><span class="nav-number">1.1.1.</span> <span class="nav-text">Nobody 用户</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#root-%E7%94%A8%E6%88%B7"><span class="nav-number">1.1.2.</span> <span class="nav-text">root 用户</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%B5%84%E6%BA%90%E9%99%90%E5%88%B6"><span class="nav-number">1.2.</span> <span class="nav-text">资源限制</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#setuid-x2F-setgid"><span class="nav-number">1.2.1.</span> <span class="nav-text">setuid&#x2F;setgid</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#setrlimit-x2F-getrlimit"><span class="nav-number">1.2.2.</span> <span class="nav-text">setrlimit&#x2F;getrlimit</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8seccomp%E9%99%90%E5%88%B6syscall"><span class="nav-number">2.</span> <span class="nav-text">使用seccomp限制syscall</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E4%BB%80%E4%B9%88%E6%98%AFseccomp"><span class="nav-number">2.1.</span> <span class="nav-text">什么是seccomp</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%A6%82%E4%BD%95%E4%BD%BF%E7%94%A8seccomp"><span class="nav-number">2.2.</span> <span class="nav-text">如何使用seccomp</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%A6%82%E4%BD%95%E6%9F%A5%E7%9C%8B%E6%98%AF%E5%90%A6%E4%BD%BF%E7%94%A8%E4%BA%86seccomp"><span class="nav-number">2.3.</span> <span class="nav-text">如何查看是否使用了seccomp</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#api-rule"><span class="nav-number">2.4.</span> <span class="nav-text">api rule</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#SCMP-SYS"><span class="nav-number">2.4.1.</span> <span class="nav-text">SCMP_SYS</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#scmp-filter-ctx"><span class="nav-number">2.4.2.</span> <span class="nav-text">scmp_filter_ctx</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#seccomp-init"><span class="nav-number">2.4.3.</span> <span class="nav-text">seccomp_init</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#seccomp-rule-addXXX"><span class="nav-number">2.4.4.</span> <span class="nav-text">seccomp_rule_addXXX</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%87%BD%E6%95%B0%E8%AF%B4%E6%98%8E"><span class="nav-number">2.4.4.1.</span> <span class="nav-text">函数说明:</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%87%BD%E6%95%B0%E5%AE%9A%E4%B9%89"><span class="nav-number">2.4.4.2.</span> <span class="nav-text">函数定义</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%8F%82%E6%95%B0%E8%AF%B4%E6%98%8E"><span class="nav-number">2.4.4.3.</span> <span class="nav-text">参数说明</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E8%BF%94%E5%9B%9E%E5%80%BC"><span class="nav-number">2.4.4.4.</span> <span class="nav-text">返回值</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%B8%BE%E4%BE%8B"><span class="nav-number">2.4.4.5.</span> <span class="nav-text">举例</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#seccomp-load"><span class="nav-number">2.4.5.</span> <span class="nav-text">seccomp_load</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#seccomp-release-3"><span class="nav-number">2.4.6.</span> <span class="nav-text">seccomp_release(3)</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%8F%82%E8%80%83%E9%93%BE%E6%8E%A5"><span class="nav-number">2.4.7.</span> <span class="nav-text">参考链接</span></a></li></ol></li></ol></li></ol></div>
        </div>
        <!--/noindex-->

        <div class="site-overview-wrap sidebar-panel">
          <div class="site-author animated" itemprop="author" itemscope itemtype="http://schema.org/Person">
  <p class="site-author-name" itemprop="name">SongyangJi</p>
  <div class="site-description" itemprop="description"></div>
</div>
<div class="site-state-wrap animated">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
        <a href="/archives/">
          <span class="site-state-item-count">251</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
          <a href="/categories/">
        <span class="site-state-item-count">45</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
          <a href="/tags/">
        <span class="site-state-item-count">109</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>

        </div>
      </div>
    </div>

    
  </aside>


    </div>

    <div class="main-inner post posts-expand">


  


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://example.com/2021/12/10/Sandbox%E7%9A%84%E5%AE%89%E5%85%A8%E6%9C%BA%E5%88%B6/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.gif">
      <meta itemprop="name" content="SongyangJi">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="JsyBlog">
      <meta itemprop="description" content="">
    </span>

    <span hidden itemprop="post" itemscope itemtype="http://schema.org/CreativeWork">
      <meta itemprop="name" content="Sandbox的安全机制 | JsyBlog">
      <meta itemprop="description" content="">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          Sandbox的安全机制
        </h1>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2021-12-10 21:51:54" itemprop="dateCreated datePublished" datetime="2021-12-10T21:51:54+08:00">2021-12-10</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar-check"></i>
      </span>
      <span class="post-meta-item-text">更新于</span>
      <time title="修改时间：2022-09-02 22:44:06" itemprop="dateModified" datetime="2022-09-02T22:44:06+08:00">2022-09-02</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/sandbox/" itemprop="url" rel="index"><span itemprop="name">sandbox</span></a>
        </span>
    </span>

  
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
        <h1 id="Sandbox的安全机制如何设计？"><a href="#Sandbox的安全机制如何设计？" class="headerlink" title="Sandbox的安全机制如何设计？"></a>Sandbox的安全机制如何设计？</h1><p>对于Linux而言，它的风格是一贯的。沙盒是进程而不是线程，这点非常明确。</p>
<h2 id="用户权限相关"><a href="#用户权限相关" class="headerlink" title="用户权限相关"></a>用户权限相关</h2><h3 id="Nobody-用户"><a href="#Nobody-用户" class="headerlink" title="Nobody 用户"></a>Nobody 用户</h3><p>在许多Unix系统与类Unix系统（如Linux）中，nobody是一个没有任何权限的用户。<br>该用户不拥有任何文件，也没有任何特殊权限。某些系统还会定义类似的用户组“nogroup”。<br>示例：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * @Author: 吉松阳</span></span><br><span class="line"><span class="comment"> * @Date: 2021/9/23</span></span><br><span class="line"><span class="comment"> * @Description: </span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;stdio.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;pwd.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="type">int</span> <span class="title function_">main</span><span class="params">()</span> &#123;</span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">passwd</span> *<span class="title">pw</span>;</span></span><br><span class="line">    <span class="type">char</span> *username = <span class="string">&quot;nobody&quot;</span>;</span><br><span class="line">    pw = getpwnam(username);</span><br><span class="line">    <span class="keyword">if</span> (!pw) &#123;</span><br><span class="line">        <span class="built_in">printf</span>(<span class="string">&quot;%s is not exist\n&quot;</span>, username);</span><br><span class="line">        <span class="keyword">return</span> <span class="number">-1</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">&quot;pw-&gt;pw_name = %s\n&quot;</span>, pw-&gt;pw_name);</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">&quot;pw-&gt;pw_passwd = %s\n&quot;</span>, pw-&gt;pw_passwd);</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">&quot;pw-&gt;pw_uid = %d\n&quot;</span>, pw-&gt;pw_uid);</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">&quot;pw-&gt;pw_gid = %d\n&quot;</span>, pw-&gt;pw_gid);</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">&quot;pw-&gt;pw_gecos = %s\n&quot;</span>, pw-&gt;pw_gecos);</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">&quot;pw-&gt;pw_dir = %s\n&quot;</span>, pw-&gt;pw_dir);</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">&quot;pw-&gt;pw_shell = %s\n&quot;</span>, pw-&gt;pw_shell);</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>下面是 MacOS Big Sur 上的 nobody 用户相关信息。<br>其中<code>/var/empty</code>表明它不拥有任何文件，<code>/usr/bin/false</code>表明它不能登录使用shell</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">pw-&gt;pw_name = nobody</span><br><span class="line">pw-&gt;pw_passwd = *</span><br><span class="line">pw-&gt;pw_uid = -2</span><br><span class="line">pw-&gt;pw_gid = -2</span><br><span class="line">pw-&gt;pw_gecos = Unprivileged User</span><br><span class="line">pw-&gt;pw_dir = /var/empty</span><br><span class="line">pw-&gt;pw_shell = /usr/bin/false</span><br></pre></td></tr></table></figure>

<p>在运行oj用户的代码的时候，是以nobody的身份运行的，意味着它的权限非常有限，不能去执行那些危险的代码。</p>
<h3 id="root-用户"><a href="#root-用户" class="headerlink" title="root 用户"></a>root 用户</h3><p>root用户，即系统的管理员。<br>sandbox程序本身需要 root权限。<br>如何区分呢？<br>将上面的代码中的用户名替换成 root, 输出为：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta prompt_">pw-&gt;</span><span class="language-bash">pw_name = root</span></span><br><span class="line"><span class="meta prompt_">pw-&gt;</span><span class="language-bash">pw_passwd = *</span></span><br><span class="line"><span class="meta prompt_">pw-&gt;</span><span class="language-bash">pw_uid = 0</span></span><br><span class="line"><span class="meta prompt_">pw-&gt;</span><span class="language-bash">pw_gid = 0</span></span><br><span class="line"><span class="meta prompt_">pw-&gt;</span><span class="language-bash">pw_gecos = System Administrator</span></span><br><span class="line"><span class="meta prompt_">pw-&gt;</span><span class="language-bash">pw_dir = /var/root</span></span><br><span class="line"><span class="meta prompt_">pw-&gt;</span><span class="language-bash">pw_shell = /bin/sh</span></span><br></pre></td></tr></table></figure>
<p>发现uid、gid 均为 0。<br>于是在运行沙箱之前判定一下程序的执行者的uid、gid是不是 root 用户即可。</p>
<h2 id="资源限制"><a href="#资源限制" class="headerlink" title="资源限制"></a>资源限制</h2><h3 id="setuid-x2F-setgid"><a href="#setuid-x2F-setgid" class="headerlink" title="setuid&#x2F;setgid"></a>setuid&#x2F;setgid</h3><ul>
<li><p>background infomation<br>内核为每个进程维护的三个UID值。<br>这三个UID分别是实际用户ID(real uid)、有效用户ID(effective uid)、保存的设置用户ID(saved set-user ID)。<br>其中 real uid 指的是运行某程序的实际用户ID（登录shell的那个用户的uid）；<br>effective uid 指的是指当前进程是以哪个用户ID来运行的；<br>保存的设置用户ID就是有效用户ID的一个副本，与SUID权限有关。<br>一般情况下 real uid 和 effective uid 相同，但是使用<code>setuid</code>、<code>chmod +s</code>之后，二者就不一定相同了。</p>
</li>
<li><p><code>setuid</code>函数定义</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;unistd.h&gt;</span></span></span><br><span class="line"><span class="type">int</span> <span class="title function_">setuid</span><span class="params">(<span class="type">uid_t</span> uid)</span>;</span><br></pre></td></tr></table></figure>
</li>
<li><p>函数说明：<br>+（1） 如果进程具有超级用户权限，那么 <code>setuid(uid_t uid)</code>会将三种 uid 全部设置成参数uid；<br> (启动sandbox其实就是要求以root身份启动的)</p>
<ul>
<li>(2) 如果 uid 等于 real uid 或者 saved set-user ID, 那么只把 effective uid 修改成 uid；</li>
<li>(3) 两种情况都不满组足，返回 -1 , errno被设置为 EPERM。</li>
</ul>
</li>
<li><p>返回值<br>执行成功则返回0； 失败则返回-1, 错误代码存于errno.</p>
</li>
<li><p>使用场景</p>
<ul>
<li>降低权限，比如在sandbox中通过让程序以 nobody 的身份来运行。</li>
<li>提高权限，但是最好注意在使用完 root 权限后建议马上执行setuid(getuid())，来抛弃root 权限，避免不必要的风险。</li>
</ul>
</li>
</ul>
<h3 id="setrlimit-x2F-getrlimit"><a href="#setrlimit-x2F-getrlimit" class="headerlink" title="setrlimit&#x2F;getrlimit"></a>setrlimit&#x2F;getrlimit</h3><ul>
<li><p>头文件:</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;sys/resource.h&gt;</span></span></span><br></pre></td></tr></table></figure>

</li>
<li><p>函数说明:<br>获取或设定资源使用限制。<br>每种资源都有相关的软硬限制:<strong>软限制</strong>是内核强加给相应资源的限制值，<strong>硬限制</strong>是软限制的最大值。<br>非授权调用进程只可以将其软限制指定为0~硬限制范围中的某个值，同时能不可逆转地降低其硬限制。<br>授权进程可以任意改变其软硬限制。<br>RLIM_INFINITY的值表示不对资源限制。</p>
</li>
<li><p>函数定义</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">getrlimit</span><span class="params">(<span class="type">int</span> resource, <span class="keyword">struct</span> rlimit *rlim)</span>;</span><br><span class="line"><span class="type">int</span> <span class="title function_">setrlimit</span><span class="params">(<span class="type">int</span> resource, <span class="type">const</span> <span class="keyword">struct</span> rlimit *rlim)</span>;</span><br></pre></td></tr></table></figure></li>
</ul>
<p>resource：可能的选择有</p>
<ul>
<li>RLIMIT_AS &#x2F;&#x2F; 进程的最大虚内存空间，字节为单位。</li>
<li>RLIMIT_CORE &#x2F;&#x2F; 内核转存文件的最大长度。</li>
<li>RLIMIT_CPU &#x2F;&#x2F; 最大允许的CPU使用时间，秒为单位。当进程达到软限制，内核将给其发送<strong>SIGXCPU</strong>信号，这一信号的默认行为是终止进程的执行。<br>然而，可以捕捉信号，处理句柄可将控制返回给主程序。<br>如果进程继续耗费CPU时间，核心会以每秒一次的频率给其发送SIGXCPU信号。<br>如果达到硬限制，那时将给进程发送 SIGKILL信号终止其执行。</li>
<li>RLIMIT_DATA &#x2F;&#x2F; 进程数据段的最大值。</li>
<li>RLIMIT_FSIZE &#x2F;&#x2F; 进程可建立的文件的最大长度。如果进程试图超出这一限制时，核心会给其发送<strong>SIGXFSZ</strong>信号，默认情况下将终止进程的执行。</li>
<li>RLIMIT_LOCKS &#x2F;&#x2F; 进程可建立的锁和租赁的最大值。</li>
<li>RLIMIT_MEMLOCK &#x2F;&#x2F; 进程可锁定在内存中的最大数据量，字节为单位。</li>
<li>RLIMIT_MSGQUEUE &#x2F;&#x2F; 进程可为POSIX消息队列分配的最大字节数。</li>
<li>RLIMIT_NICE &#x2F;&#x2F; 进程可通过setpriority() 或 nice()调用设置的最大完美值。</li>
<li>RLIMIT_NOFILE &#x2F;&#x2F; 指定比进程可打开的最大文件描述词大一的值，超出此值，将会产生EMFILE错误。</li>
<li>RLIMIT_NPROC &#x2F;&#x2F; 用户可拥有的最大进程数。</li>
<li>RLIMIT_RTPRIO &#x2F;&#x2F; 进程可通过sched_setscheduler 和 sched_setparam设置的最大实时优先级。</li>
<li>RLIMIT_SIGPENDING &#x2F;&#x2F; 用户可拥有的最大挂起信号数。</li>
<li>RLIMIT_STACK &#x2F;&#x2F; 最大的进程栈，以字节为单位。</li>
</ul>
<p>rlimit：描述资源软硬限制的结构体，原型如下</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">rlimit</span> &#123;</span></span><br><span class="line">	<span class="type">rlim_t</span>  rlim_cur;               <span class="comment">/* current (soft) limit 软限制 */</span></span><br><span class="line">	<span class="type">rlim_t</span>  rlim_max;               <span class="comment">/* maximum value for rlim_cur 硬限制 */</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>


<ul>
<li><p>返回值<br><strong>成功执行时，返回 0 。失败返回 -1</strong> 。<br>errno被设为以下的某个值：</p>
<ul>
<li>EFAULT：rlim指针指向的空间不可访问</li>
<li>EINVAL：参数无效</li>
<li>EPERM：增加资源限制值时，权能不允许</li>
</ul>
</li>
<li><p>参考链接：<br><a target="_blank" rel="noopener" href="https://man7.org/linux/man-pages/man2/getrlimit.2.html">getrlimit(2) — Linux manual page</a></p>
</li>
</ul>
<h1 id="使用seccomp限制syscall"><a href="#使用seccomp限制syscall" class="headerlink" title="使用seccomp限制syscall"></a>使用seccomp限制syscall</h1><h2 id="什么是seccomp"><a href="#什么是seccomp" class="headerlink" title="什么是seccomp"></a>什么是seccomp</h2><p>seccomp（全称 <strong>secure computing mode</strong>）是linux kernel从2.6.23版本开始所支持的一种安全机制。<br>seccomp是一种<strong>内核中的安全机制</strong>,正常情况下,程序可以使用所有的syscall,这是不安全的。<br>比如劫持程序流后通过execve的syscall来<code>getshell</code>。<br>通过seccomp我们可以在程序中禁用掉某些syscall,这样就算劫持了程序流也只能调用部分的syscall了.</p>
<p><strong>通过seccomp，我们限制程序使用某些系统调用，这样可以减少系统的暴露面，同时是程序进入一种“安全”的状态。</strong><br>详细介绍可参考seccomp内核文档(见参考链接)。</p>
<h2 id="如何使用seccomp"><a href="#如何使用seccomp" class="headerlink" title="如何使用seccomp"></a>如何使用seccomp</h2><p>seccomp可以通过系统调用ptrctl(2)或者通过系统调用seccomp(2)开启，前提是内核配置中开启了CONFIG_SECCOMP和CONFIG_SECCOMP_FILTER。</p>
<p>seccomp支持两种模式：<strong>SECCOMP_MODE_STRICT</strong> 和 <strong>SECCOMP_MODE_FILTER</strong>。</p>
<ul>
<li>在SECCOMP_MODE_STRICT模式下，进程不能使用<code>read(2)</code>、<code>write(2)</code>、<code>_exit(2)</code>和<code>sigreturn(2)</code>以外的其他系统调用。</li>
<li>在SECCOMP_MODE_FILTER模式下，可以利用BerkeleyPacket Filter配置哪些系统调用及它们的参数可以被进程使用。</li>
</ul>
<h2 id="如何查看是否使用了seccomp"><a href="#如何查看是否使用了seccomp" class="headerlink" title="如何查看是否使用了seccomp"></a>如何查看是否使用了seccomp</h2><p>通常有两种方法：<br>利用<code>prctl(2)</code>的PR_GET_SECCOMP的参数获取当前进程的seccomp状态。</p>
<ul>
<li>返回值0表示没有使用seccomp;</li>
<li>返回值2表示使用了seccomp并处于SECCOMP_MODE_FILTER模式； </li>
<li>其他情况进程会被SIGKILL信号杀死。</li>
</ul>
<p>从Linux3.8开始，可以利用&#x2F;proc&#x2F;$pid&#x2F;status中的Seccomp字段查看。如果没有seccomp字段，说明内核不支持seccomp。</p>
<ul>
<li><p>举例:<br>查看mysql服务的seccomp的状态，发现并没有进入安全限制模式。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">cat /proc/`pidof mysqld`/status</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">输出</span></span><br><span class="line">Name:	mysqld</span><br><span class="line">......</span><br><span class="line">Seccomp:	0</span><br><span class="line">Seccomp_filters:	0</span><br></pre></td></tr></table></figure>
<p>在sandbox环境下执行 python3 脚本，<br>查看次进程的seccomp的状态，发现进程处于SECCOMP_MODE_FILTER模式 。</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">Name:	python3</span><br><span class="line">......</span><br><span class="line">Seccomp:	2</span><br><span class="line">Seccomp_filters:	1</span><br></pre></td></tr></table></figure>
</li>
<li><p>代码示例<br>使用 <code>syscall</code> 调用 execve，如果没有安全限制的话，会正常进入 shell</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string">&lt;unistd.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string">&lt;sys/syscall.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">include</span><span class="string">&lt;seccomp.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="type">int</span> <span class="title function_">main</span><span class="params">()</span> &#123;</span><br><span class="line"></span><br><span class="line">    scmp_filter_ctx ctx; <span class="comment">// scmp 过滤上下文</span></span><br><span class="line">    ctx = seccomp_init(SCMP_ACT_ALLOW); <span class="comment">// 初始化过滤状态为允许所有系统调用</span></span><br><span class="line">    seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(execve), <span class="number">0</span>); <span class="comment">// 添加需要限制的系统调用</span></span><br><span class="line">    seccomp_load(ctx); <span class="comment">// 装载上下文</span></span><br><span class="line"></span><br><span class="line">    <span class="type">char</span> *filename = <span class="string">&quot;/bin/sh&quot;</span>;</span><br><span class="line">    <span class="type">char</span> *argv[] = &#123;<span class="string">&quot;/bin/sh&quot;</span>, <span class="literal">NULL</span>&#125;;</span><br><span class="line">    <span class="type">char</span> *envp[] = &#123;<span class="literal">NULL</span>&#125;;</span><br><span class="line"></span><br><span class="line">    syscall(SYS_execve, filename, argv, envp); <span class="comment">// execve</span></span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>编译</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">gcc -o ban ban.c -l seccomp</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">须先实现安装</span> </span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">sudo apt install libseccomp-dev libseccomp2 seccomp</span></span><br></pre></td></tr></table></figure>
<p>运行程序</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">songyangji@SongyangJi-Ubuntu-DeskStop:~/桌面$ ./ban</span><br><span class="line">错误的系统调用 (核心已转储) # Bad system call (core dumped)</span><br></pre></td></tr></table></figure></li>
</ul>
<h2 id="api-rule"><a href="#api-rule" class="headerlink" title="api rule"></a>api rule</h2><h3 id="SCMP-SYS"><a href="#SCMP-SYS" class="headerlink" title="SCMP_SYS"></a>SCMP_SYS</h3><p>根据系统调用名获取系统调用号，虽然你可以直接使用 <code>__NR_syscall</code> 直接指定，但是为了跨平台最好使用它获取。</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">SCMP_SYS</span><span class="params">(syscall_name)</span>;</span><br></pre></td></tr></table></figure>

<h3 id="scmp-filter-ctx"><a href="#scmp-filter-ctx" class="headerlink" title="scmp_filter_ctx"></a>scmp_filter_ctx</h3><p>结构体定义</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typedef</span> <span class="type">void</span> * scmp_filter_ctx;</span><br></pre></td></tr></table></figure>
<p>seccmp的过滤器上下文，保存、传递了我们传入的系统调用过滤条件。</p>
<h3 id="seccomp-init"><a href="#seccomp-init" class="headerlink" title="seccomp_init"></a>seccomp_init</h3><ul>
<li><p>函数说明:<br>seccomp_init的作用就是初始化 scmp_filter_ctx结构。<br>需要注意的是，任何其他libseccomp中的函数调用，必须在seccomp_init之后。</p>
</li>
<li><p>函数定义</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">scmp_filter_ctx <span class="title function_">seccomp_init</span><span class="params">(<span class="type">uint32_t</span> def_action)</span>; </span><br></pre></td></tr></table></figure>
</li>
<li><p>返回值<br>成功返回scmp_filter_ctx（过滤器上下文） ctx；<br>失败返回NULL</p>
</li>
<li><p>参数说明<br>def_action用于指定默认行为，有效动作值如下：（当线程调用了<code>seccomp</code>过滤规则中没有相关配置规则的系统调用时触发）</p>
<ul>
<li>SCMP_ACT_KILL<br>线程将会被内核以SIGSYS信号终止；</li>
<li>SCMP_ACT_KILL_PROCESS<br>整个进程被终止；</li>
<li>SCMP_ACT_TRAP<br>线程将会抛出一个SIGSYS信号；</li>
<li>SCMP_ACT_ERRNO(uint16_t errno)<br>线程调用与筛选规则匹配的系统调用时，它将收到一个errno的返回值；</li>
<li>SCMP_ACT_TRACE(uint16_t msg_num)<br>略</li>
<li>SCMP_ACT_LOG<br>不会对调用系统调用的线程产生任何影响，但系统调用会被记录到日志。</li>
<li>SCMP_ACT_ALLOW<br>不会对调用系统调用的线程产生任何影响。</li>
</ul>
</li>
</ul>
<h3 id="seccomp-rule-addXXX"><a href="#seccomp-rule-addXXX" class="headerlink" title="seccomp_rule_addXXX"></a>seccomp_rule_addXXX</h3><h4 id="函数说明"><a href="#函数说明" class="headerlink" title="函数说明:"></a>函数说明:</h4><p>  这个函数组都会向当前seccomp过滤器添加新的过滤规则。</p>
<blockquote>
<p>调用应用程序提供的所有过滤器规则被组合成一个联合，并带有额外的逻辑来消除冗余的系统调用过滤器。<br>例如，如果添加了一条规则，该规则允许给定的系统调用具有一组特定的参数值，<br>然后又添加了一条规则，该规则允许相同的系统调用而不管参数值如何，<br>那么第一个更具体的规则将有效地从过滤器中删除第二个更通用的规则。</p>
</blockquote>
<h4 id="函数定义"><a href="#函数定义" class="headerlink" title="函数定义"></a>函数定义</h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">seccomp_rule_add</span><span class="params">(scmp_filter_ctx ctx, <span class="type">uint32_t</span> action,</span></span><br><span class="line"><span class="params">                            <span class="type">int</span> syscall, <span class="type">unsigned</span> <span class="type">int</span> arg_cnt, ...)</span>;</span><br><span class="line"><span class="type">int</span> <span class="title function_">seccomp_rule_add_exact</span><span class="params">(scmp_filter_ctx ctx, <span class="type">uint32_t</span> action,</span></span><br><span class="line"><span class="params">                                  <span class="type">int</span> syscall, <span class="type">unsigned</span> <span class="type">int</span> arg_cnt, ...)</span>;</span><br><span class="line"></span><br><span class="line"><span class="type">int</span> <span class="title function_">seccomp_rule_add_array</span><span class="params">(scmp_filter_ctx ctx,</span></span><br><span class="line"><span class="params">                                  <span class="type">uint32_t</span> action, <span class="type">int</span> syscall,</span></span><br><span class="line"><span class="params">                                  <span class="type">unsigned</span> <span class="type">int</span> arg_cnt,</span></span><br><span class="line"><span class="params">                                  <span class="type">const</span> <span class="keyword">struct</span> scmp_arg_cmp *arg_array)</span>;</span><br><span class="line"><span class="type">int</span> <span class="title function_">seccomp_rule_add_exact_array</span><span class="params">(scmp_filter_ctx ctx,</span></span><br><span class="line"><span class="params">                                        <span class="type">uint32_t</span> action, <span class="type">int</span> syscall,</span></span><br><span class="line"><span class="params">                                        <span class="type">unsigned</span> <span class="type">int</span> arg_cnt,</span></span><br><span class="line"><span class="params">                                        <span class="type">const</span> <span class="keyword">struct</span> scmp_arg_cmp *arg_array)</span>;</span><br></pre></td></tr></table></figure>


<h4 id="参数说明"><a href="#参数说明" class="headerlink" title="参数说明"></a>参数说明</h4><ul>
<li><ol>
<li>action有效动作值如下：（当线程调用了<code>seccomp</code>过滤规则中有相关配置规则的系统调用时触发）</li>
</ol>
<ul>
<li>SCMP_ACT_KILL<br>线程将会被内核终止；</li>
<li>SCMP_ACT_KILL_PROCESS<br>整个进程被终止；</li>
<li>SCMP_ACT_TRAP<br>线程将会抛出一个SIGSYS信号；</li>
<li>SCMP_ACT_ERRNO(uint16_t errno)<br>线程调用与筛选规则匹配的系统调用时，它将收到一个errno的返回值；</li>
<li>SCMP_ACT_TRACE(uint16_t msg_num)<br>略</li>
<li>SCMP_ACT_LOG<br>会对调用系统调用的线程产生任何影响，但系统调用会被记录到日志。</li>
<li>SCMP_ACT_ALLOW<br>不会对调用系统调用的线程产生任何影响（也就是允许调用这个system call）。</li>
<li>SCMP_ACT_NOTIFY<br>略</li>
</ul>
</li>
<li><ol start="2">
<li>arg_cnt 指定规则配置的系统调用的参数的匹配情况的个数（因为后面是一个变长数组）</li>
</ol>
</li>
<li><ol start="3">
<li>边长数组的元素是 <code>scmp_arg_cmp</code> 结构体，定义如下。</li>
</ol>
</li>
</ul>
<p>系统调用的参数比较规则相关定义：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Comparison operators</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="class"><span class="keyword">enum</span> <span class="title">scmp_compare</span> &#123;</span></span><br><span class="line">	_SCMP_CMP_MIN = <span class="number">0</span>,</span><br><span class="line">	SCMP_CMP_NE = <span class="number">1</span>,		<span class="comment">/**&lt; not equal */</span></span><br><span class="line">	SCMP_CMP_LT = <span class="number">2</span>,		<span class="comment">/**&lt; less than */</span></span><br><span class="line">	SCMP_CMP_LE = <span class="number">3</span>,		<span class="comment">/**&lt; less than or equal */</span></span><br><span class="line">	SCMP_CMP_EQ = <span class="number">4</span>,		<span class="comment">/**&lt; equal */</span></span><br><span class="line">	SCMP_CMP_GE = <span class="number">5</span>,		<span class="comment">/**&lt; greater than or equal */</span></span><br><span class="line">	SCMP_CMP_GT = <span class="number">6</span>,		<span class="comment">/**&lt; greater than */</span></span><br><span class="line">	SCMP_CMP_MASKED_EQ = <span class="number">7</span>,		<span class="comment">/**&lt; masked equality */</span></span><br><span class="line">	_SCMP_CMP_MAX,</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Argument datum</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">typedef</span> <span class="type">uint64_t</span> <span class="type">scmp_datum_t</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Argument / Value comparison definition</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">scmp_arg_cmp</span> &#123;</span></span><br><span class="line">	<span class="type">unsigned</span> <span class="type">int</span> arg;	<span class="comment">/**&lt; argument number, starting at 0 */</span></span><br><span class="line">	<span class="class"><span class="keyword">enum</span> <span class="title">scmp_compare</span> <span class="title">op</span>;</span>	<span class="comment">/**&lt; the comparison op, e.g. SCMP_CMP_* */</span></span><br><span class="line">	<span class="type">scmp_datum_t</span> datum_a;</span><br><span class="line">	<span class="type">scmp_datum_t</span> datum_b;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>有效比较操作值（ op ）如下：</p>
<ul>
<li><p>SCMP_CMP_NE<br>参数值不等于基准值时匹配，例如：<br>SCMP_CMP( arg , SCMP_CMP_NE , datum )</p>
</li>
<li><p>SCMP_CMP_LT<br>参数值小于基准值时匹配，例如：<br>SCMP_CMP( arg , SCMP_CMP_LT , datum )</p>
</li>
<li><p>SCMP_CMP_LE<br>参数值小于或等于基准值时匹配，例如：<br>SCMP_CMP( arg , SCMP_CMP_LE , datum )</p>
</li>
<li><p>SCMP_CMP_EQ<br>参数值等于基准值时匹配，例如：<br>SCMP_CMP( arg , SCMP_CMP_EQ , datum )</p>
</li>
<li><p>SCMP_CMP_GE<br>参数值大于或等于基准值时匹配，例如：<br>SCMP_CMP( arg , SCMP_CMP_GE , datum )</p>
</li>
<li><p>SCMP_CMP_GT<br>参数值大于基准值时匹配，例如：<br>SCMP_CMP( arg , SCMP_CMP_GT , datum )</p>
</li>
<li><p>SCMP_CMP_MASKED_EQ<br>当掩码参数值等于掩码基准值时匹配，例如：<br>SCMP_CMP( arg , SCMP_CMP_MASKED_EQ , mask , datum )</p>
</li>
</ul>
<p>注意，scmp_arg_cmp 此结构不能直接生成，需要调用它提供的宏生成，有如下宏：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">struct</span> scmp_arg_cmp <span class="title function_">SCMP_CMP</span><span class="params">(<span class="type">unsigned</span> <span class="type">int</span> arg,</span></span><br><span class="line"><span class="params">                                    <span class="keyword">enum</span> scmp_compare op, ...)</span>;</span><br><span class="line">       <span class="keyword">struct</span> scmp_arg_cmp <span class="title function_">SCMP_A0</span><span class="params">(<span class="keyword">enum</span> scmp_compare op, ...)</span>;</span><br><span class="line">       <span class="keyword">struct</span> scmp_arg_cmp <span class="title function_">SCMP_A1</span><span class="params">(<span class="keyword">enum</span> scmp_compare op, ...)</span>;</span><br><span class="line">       <span class="keyword">struct</span> scmp_arg_cmp <span class="title function_">SCMP_A2</span><span class="params">(<span class="keyword">enum</span> scmp_compare op, ...)</span>;</span><br><span class="line">       <span class="keyword">struct</span> scmp_arg_cmp <span class="title function_">SCMP_A3</span><span class="params">(<span class="keyword">enum</span> scmp_compare op, ...)</span>;</span><br><span class="line">       <span class="keyword">struct</span> scmp_arg_cmp <span class="title function_">SCMP_A4</span><span class="params">(<span class="keyword">enum</span> scmp_compare op, ...)</span>;</span><br><span class="line">       <span class="keyword">struct</span> scmp_arg_cmp <span class="title function_">SCMP_A5</span><span class="params">(<span class="keyword">enum</span> scmp_compare op, ...)</span>;</span><br><span class="line"></span><br><span class="line">       <span class="keyword">struct</span> scmp_arg_cmp <span class="title function_">SCMP_CMP64</span><span class="params">(<span class="type">unsigned</span> <span class="type">int</span> arg,</span></span><br><span class="line"><span class="params">                                    <span class="keyword">enum</span> scmp_compare op, ...)</span>;</span><br><span class="line">       <span class="keyword">struct</span> scmp_arg_cmp <span class="title function_">SCMP_A0_64</span><span class="params">(<span class="keyword">enum</span> scmp_compare op, ...)</span>;</span><br><span class="line">       <span class="keyword">struct</span> scmp_arg_cmp <span class="title function_">SCMP_A1_64</span><span class="params">(<span class="keyword">enum</span> scmp_compare op, ...)</span>;</span><br><span class="line">       <span class="keyword">struct</span> scmp_arg_cmp <span class="title function_">SCMP_A2_64</span><span class="params">(<span class="keyword">enum</span> scmp_compare op, ...)</span>;</span><br><span class="line">       <span class="keyword">struct</span> scmp_arg_cmp <span class="title function_">SCMP_A3_64</span><span class="params">(<span class="keyword">enum</span> scmp_compare op, ...)</span>;</span><br><span class="line">       <span class="keyword">struct</span> scmp_arg_cmp <span class="title function_">SCMP_A4_64</span><span class="params">(<span class="keyword">enum</span> scmp_compare op, ...)</span>;</span><br><span class="line">       <span class="keyword">struct</span> scmp_arg_cmp <span class="title function_">SCMP_A5_64</span><span class="params">(<span class="keyword">enum</span> scmp_compare op, ...)</span>;</span><br><span class="line"></span><br><span class="line">       <span class="keyword">struct</span> scmp_arg_cmp <span class="title function_">SCMP_CMP32</span><span class="params">(<span class="type">unsigned</span> <span class="type">int</span> arg,</span></span><br><span class="line"><span class="params">                                    <span class="keyword">enum</span> scmp_compare op, ...)</span>;</span><br><span class="line">       <span class="keyword">struct</span> scmp_arg_cmp <span class="title function_">SCMP_A0_32</span><span class="params">(<span class="keyword">enum</span> scmp_compare op, ...)</span>;</span><br><span class="line">       <span class="keyword">struct</span> scmp_arg_cmp <span class="title function_">SCMP_A1_32</span><span class="params">(<span class="keyword">enum</span> scmp_compare op, ...)</span>;</span><br><span class="line">       <span class="keyword">struct</span> scmp_arg_cmp <span class="title function_">SCMP_A2_32</span><span class="params">(<span class="keyword">enum</span> scmp_compare op, ...)</span>;</span><br><span class="line">       <span class="keyword">struct</span> scmp_arg_cmp <span class="title function_">SCMP_A3_32</span><span class="params">(<span class="keyword">enum</span> scmp_compare op, ...)</span>;</span><br><span class="line">       <span class="keyword">struct</span> scmp_arg_cmp <span class="title function_">SCMP_A4_32</span><span class="params">(<span class="keyword">enum</span> scmp_compare op, ...)</span>;</span><br><span class="line">       <span class="keyword">struct</span> scmp_arg_cmp <span class="title function_">SCMP_A5_32</span><span class="params">(<span class="keyword">enum</span> scmp_compare op, ...)</span>;</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>解释一下上面的这么多宏的功能分类依据，A{0-5}中的0、1、2、3、4、5用于指定系统调用的那个参数，<br>32还是64自然是指定32位机器还是64位机器，<br>SCMP_CMP的第一个参数<code>unsigned int arg</code>的功能就是<code>A&#123;$arg_num&#125;</code>中的<code>$arg_num</code>，<br>所有宏的第一个参数<code>op</code>就是用于指定比较的规则，如上已经介绍过。</p>
<h4 id="返回值"><a href="#返回值" class="headerlink" title="返回值"></a>返回值</h4><p>函数成功时返回零；<br>失败时返回负的errno值。</p>
<h4 id="举例"><a href="#举例" class="headerlink" title="举例"></a>举例</h4><p>1. </p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), <span class="number">1</span>, SCMP_CMP(<span class="number">1</span>, SCMP_CMP_MASKED_EQ, O_WRONLY | O_RDWR, <span class="number">0</span>))</span><br></pre></td></tr></table></figure>
<p>指定<code>open(const *path, int oflags)</code>系统调用的<code>oflags</code>参数如果既没有O_WRONLY，也没有O_RDWR（二进制对应位），就是允许的，<br>换言之这条规则禁用掉了 open的 w、rw。</p>
<h3 id="seccomp-load"><a href="#seccomp-load" class="headerlink" title="seccomp_load"></a>seccomp_load</h3><ul>
<li><p>函数说明:<br>将ctx提供的seccomp过滤器加载到内核中；<br>如果函数成功，新的 seccomp 过滤器将在函数返回时处于活动状态</p>
</li>
<li><p>函数定义</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">seccomp_load</span><span class="params">(scmp_filter_ctx ctx)</span>;</span><br></pre></td></tr></table></figure>
</li>
<li><p>返回值<br>成功时返回0，失败时返回以下错误码：<br>-ECANCELED<br>  There was a system failure beyond the control of the<br>library.<br>-EFAULT<br>  Internal libseccomp failure.<br>-EINVAL<br>  Invalid input, either the context or architecture token is invalid.<br>-ENOMEM<br>  The library was unable to allocate enough memory.<br>-ESRCH<br>  Unable to load the filter due to thread issues.</p>
</li>
</ul>
<h3 id="seccomp-release-3"><a href="#seccomp-release-3" class="headerlink" title="seccomp_release(3)"></a>seccomp_release(3)</h3><ul>
<li><p>函数说明:<br>释放ctx 中的 seccomp 过滤器结构的内存，该过滤器首先由seccomp_init(3)或seccomp_reset(3)初始化，<br>并释放与给定 seccomp 过滤器上下文关联的任何内存。<br>加载到内核中的任何 seccomp过滤器不受影响。</p>
</li>
<li><p>函数定义</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">void</span> <span class="title function_">seccomp_release</span><span class="params">(scmp_filter_ctx ctx)</span>;</span><br></pre></td></tr></table></figure></li>
</ul>
<h3 id="参考链接"><a href="#参考链接" class="headerlink" title="参考链接"></a>参考链接</h3><p>  <a target="_blank" rel="noopener" href="https://www.kernel.org/doc/Documentation/prctl/seccomp_filter.txt">Secure Computing with filters</a><br>  <a target="_blank" rel="noopener" href="https://man7.org/linux/man-pages/man3/seccomp_init.3.html">seccomp_init(3)</a><br>  <a target="_blank" rel="noopener" href="https://man7.org/linux/man-pages/man3/seccomp_rule_add.3.html">seccomp_rule_add(3)</a><br>  <a target="_blank" rel="noopener" href="https://man7.org/linux/man-pages/man3/seccomp_load.3.html">seccomp_load(3)</a><br>  <a target="_blank" rel="noopener" href="https://man7.org/linux/man-pages/man3/seccomp_release.3.html">seccomp_release(3)</a></p>
<blockquote>
<p>参考链接</p>
<p><a target="_blank" rel="noopener" href="https://zh.wikipedia.org/wiki/%E6%B2%99%E7%9B%92_(%E9%9B%BB%E8%85%A6%E5%AE%89%E5%85%A8)">沙箱安全</a></p>
</blockquote>

    </div>

    
    
    

    <footer class="post-footer">
          <div class="post-tags">
              <a href="/tags/Linux/" rel="tag"># Linux</a>
              <a href="/tags/%E5%AE%89%E5%85%A8/" rel="tag"># 安全</a>
              <a href="/tags/sandbox/" rel="tag"># sandbox</a>
          </div>

        

          <div class="post-nav">
            <div class="post-nav-item">
                <a href="/2021/12/10/LinkLayer/" rel="prev" title="LinkLayer">
                  <i class="fa fa-chevron-left"></i> LinkLayer
                </a>
            </div>
            <div class="post-nav-item">
                <a href="/2021/12/12/ConcurrentHashMap/" rel="next" title="JUC之并发安全的HashMap —— ConcurrentHashMap">
                  JUC之并发安全的HashMap —— ConcurrentHashMap <i class="fa fa-chevron-right"></i>
                </a>
            </div>
          </div>
    </footer>
  </article>
</div>






</div>
  </main>

  <footer class="footer">
    <div class="footer-inner">


<div class="copyright">
  &copy; 
  <span itemprop="copyrightYear">2023</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">SongyangJi</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" rel="noopener" target="_blank">Hexo</a> & <a href="https://theme-next.js.org/muse/" rel="noopener" target="_blank">NexT.Muse</a> 强力驱动
  </div>

    </div>
  </footer>

  
  <div class="toggle sidebar-toggle" role="button">
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
  </div>
  <div class="sidebar-dimmer"></div>
  <div class="back-to-top" role="button" aria-label="返回顶部">
    <i class="fa fa-arrow-up fa-lg"></i>
    <span>0%</span>
  </div>

<noscript>
  <div class="noscript-warning">Theme NexT works best with JavaScript enabled</div>
</noscript>


  
  <script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js" integrity="sha256-XL2inqUJaslATFnHdJOi9GfQ60on8Wx1C2H8DYiN1xY=" crossorigin="anonymous"></script>
<script src="/js/comments.js"></script><script src="/js/utils.js"></script><script src="/js/motion.js"></script><script src="/js/schemes/muse.js"></script><script src="/js/next-boot.js"></script>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/hexo-generator-searchdb/1.4.1/search.js" integrity="sha256-1kfA5uHPf65M5cphT2dvymhkuyHPQp5A53EGZOnOLmc=" crossorigin="anonymous"></script>
<script src="/js/third-party/search/local-search.js"></script>





  





</body>
</html>
